package com.easybuilder.core.im.netty.websocket;

import com.alibaba.fastjson.JSONObject;
import com.easybuilder.common.enums.WSMessageType;
import com.easybuilder.common.utils.SpringUtil;
import com.easybuilder.core.im.dto.WSMessageDTO;
import com.easybuilder.core.im.service.GroupChatService;
import com.easybuilder.core.im.service.OfflinePushService;
import com.easybuilder.core.im.service.SignleChatService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.stereotype.Component;

// TextWebSocketFrame表示一个文本帧
public class WebsocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /** 离线消息推送服务 */
    private static OfflinePushService offlinePushService = SpringUtil.getBean(OfflinePushService.class);
    /** 单聊处理服务 */
    private static SignleChatService signleChatService = SpringUtil.getBean(SignleChatService.class);
    /** 群聊处理服务 */
    private static GroupChatService groupChatService = SpringUtil.getBean(GroupChatService.class);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        Channel channel = channelHandlerContext.channel();
        String data = textWebSocketFrame.text();
        try {
            WSMessageDTO wsMessageDTO = JSONObject.parseObject(data, WSMessageDTO.class);
            // 消息类型
            switch (WSMessageType.getName(wsMessageDTO.getType())) {
                // 100：当系统用户创建连接成功后，绑定用户id与通道; 此时需要额外检查下，该用户是否有未接收的消息，如果有则立即推送
                case "BIND_USER_CHANNEL" :
                    // 保存用户通道
                    WebsocketContext.addUserChannel(wsMessageDTO.getMessage().getSenderId(), channel);
                    // 推送离线消息
                    offlinePushService.push(wsMessageDTO.getMessage().getSenderId(), channel);
                    break;
                // 客户端发送单聊消息给指定用户
                case "SEND_SINGLE_MESSAGE" : signleChatService.sendMessage(wsMessageDTO, channel); break;
                // 客户端接收消息成功
                case "MESSAGE_RECEIVED_SUCCESS" : signleChatService.receiveSuccess(wsMessageDTO.getIds()); break;
                // 客户端读取消息成功
                case "MESSAGE_READ_SUCCESS": signleChatService.readSuccess(wsMessageDTO.getIds()); break;
                default:
                    System.out.println("netty websocket : 暂无此消息类型的处理方案");
            }

        } catch (Exception e) {
            System.out.println("netty 服务端处理消息失败！消息内容：" + data);
            e.printStackTrace();
        }
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("--------------------------handlerAdded--------------------------");
        System.out.println(ctx.channel().id().asLongText());
        // 建立连接后，先把通道保存到容器（先以游客通道进行保存；等客户端建立连接成功后，如果发现是系统用户，立即发送一条消息，保存用户id与通道的对应关系）
        WebsocketContext.addVisitorChannel(ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("产生异常：" + cause.getMessage());
        ctx.close();
        WebsocketContext.removeVisitor(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("--------------------------handlerRemoved--------------------------");
        System.out.println("客户端"+ctx.channel().remoteAddress()+ "断开连接");
        // 移除容器中的通道
        WebsocketContext.removeVisitor(ctx.channel());
    }
}
